<?php

//TODO 这是干啥的
define('_UC_LOGGED_SITE_SKEY', 'logged_sites');

class CnvpServerSSO {

    static private $_SessKey = '_cnvp_user';
    static private $_sitesMap = array();
    static private $_coSitesInfo = array();

    //初始化函数
    static private function _init() {
        session_write_close();
        ini_set('session.cookie_lifetime', 0);
        ini_set('session.gc_maxlifetime', 3600);
    }

    // 用户验证中心 登陆用户处理
    static public function loginUCenter($username, $password, $ip, $siteFlag, $remember = false) {
        self::_init();        
        session_destroy();
        session_start();
        $ret = array();
        //TODO 去model层验证用户登录
//        $arr_login_res = uc_user_login($username, $password, $ip);
        $arr_login_res = self::userAuth($username, $password, $ip);
        $res_login = $arr_login_res['status'];
        $res_userinfo = $arr_login_res['userinfo'];
        $ret['resultFlag'] = $res_login;

        if ($res_login < 1) {
            //登陆失败
        } else {
            //登陆成功
            $_SESSION[self::$_SessKey] = $arr_login_res;
            //用户名+用户+奇怪字符的MD5加密字符串
            $_SESSION[self::$_SessKey]['salt'] =
                    self::_getUserPassSalt($_SESSION[self::$_SessKey]['username'], $_SESSION[self::$_SessKey]['password']);
            //初始化返回数据
            $ret['userinfo'] = $_SESSION[self::$_SessKey];            
            $ret['sessID'] = session_id();
            //配置加密数据，用户信息，操作信息
            $uinfo = array();
            $_timestamp = time();
            $_rawCode = array(
                'uid' => $res_userinfo['id'],
                'username' => $res_userinfo['username'],
                'nickname' => $res_userinfo['nickname'],
                'deptid' => $res_userinfo['deptid'],
                'action' => 'setSid',
                'sid' => $ret['sessID'],
                'time' => $_timestamp,
            );
            if ($remember) {
                $uinfo = array(
                    'remember' => 1,
                    'username' => $username,
                    'password' => $password
                );
            }
            //合作站点的全域cookie设置脚本地址
            $ret['script'] = '';
            $_rawStr = http_build_query(array_merge($_rawCode, $uinfo));
            $synScript = '';
            //生成合作中心站回调登陆接口script(设置用户中心的统一session id)
            self::_createCoSitesInfo();
            foreach ((array) self::$_coSitesInfo as $_siteInfo) {
                $_code = self::authcode($_rawStr, 'ENCODE', $_siteInfo['key']);
                $_src = $_siteInfo['url'] . '?code='.$_code.'&time=' . $_timestamp; //' . $_code . '
                $synScript .= '<script src="' . $_src . '"></script>';
            }
            $ret['script'] = "<![CDATA[" . $synScript . "]]>";
            //记住已登陆战
            self::registerLoggedSite($siteFlag, $ret['sessID']);

            unset($ret['userinfo']['salt']);
        }

        return $ret;
    }

    //根据sid，获取当前登陆的用户信息
    static public function getOnlineUser($sessId, $siteFlag) {
        self::_init();
        session_id(trim($sessId));
        session_start();

        $ret = array();
        @$_userinfo = $_SESSION[self::$_SessKey];
        if (isset($_userinfo['username']) && isset($_userinfo['password']) &&
                self::_getUserPassSalt($_userinfo['username'], $_userinfo['password'])) {
            $ret['resultFlag'] = "1";
            $ret['userinfo'] = $_userinfo;
            //记住已登陆战
            self::registerLoggedSite($siteFlag, $sessId);
            unset($ret['userinfo']['salt']);
        } else {
            $ret['resultFlag'] = "0";
        }

        return ($ret);
    }

    // 根据sid，获取当前登陆的用户信息
    static public function getOnlineUserDetail($sessId, $siteFlag, $fields) {
        self::_init();
        session_id(trim($sessId));
        session_start();

        $ret = array();
        @$_userinfo = $_SESSION[self::$_SessKey];
        if (isset($_userinfo['username']) && isset($_userinfo['password']) &&
                self::_getUserPassSalt($_userinfo['username'], $_userinfo['password'])) {
            $ret['resultFlag'] = "1";
            $ret['userinfo'] = uc_user_detail_get($_userinfo['username'], 0, $fields);
            //记住已登陆战
            self::registerLoggedSite($siteFlag, $sessId);
            unset($ret['userinfo']['salt']);
        } else {
            $ret['resultFlag'] = "0";
        }

        return ($ret);
    }

    // 将已经成功获取sid的站点，记录到对应的session中，以便后面针对性的登出站点   
    static public function registerLoggedSite($site_flag, $sessId) {
        if (!in_array($site_flag, $_SESSION[_UC_LOGGED_SITE_SKEY])) {
            $_SESSION[_UC_LOGGED_SITE_SKEY][] = $site_flag;
        }
    }

    // 登出全站处理
    static public function logoutUCenter($sessId) {
        self::_init();
        session_id(trim($sessId));
        session_start();

        $_SESSION = array();
        return empty($_SESSION) ? true : false;
    }

    // 获取登出全站的脚本（需要在客户端输出）
    static public function fetchLogoutScript($sessId, $siteFlag) {
        self::_init();
        session_id($sessId);
        session_start();
        self::_createSitesMap();
        $sOUt = '';
        foreach ((array) $_SESSION[_UC_LOGGED_SITE_SKEY] as $_siteId) {
            if ($_siteId != $siteFlag) {
                $_url = self::$_sitesMap[intval($_siteId)]['logoutUrl'];
                $sOUt .= '<script type="text/javascript" src="' . $_url . '"></script>';
            }
        }

        //合作中心站回调登出接口(设置用户中心的统一session id)
        self::_createCoSitesInfo();
        $uinfo = array();
        $_timestamp = time();
        $_rawCode = array(
            'action' => 'removeSid',
            'time' => $_timestamp,
        );
        $_rawStr = http_build_query($_rawCode);

        //合作站点的全域cookie设置脚本地址
        foreach ((array) self::$_coSitesInfo as $_siteInfo) {
            $_code = self::authcode($_rawStr, 'ENCODE', $_siteInfo['key']);
            $_src = $_siteInfo['url'] . '?code=' . $_code . '&time=' . $_timestamp;
            $sOUt .= '<script type="text/javascript" src="' . $_src . '"></script>';
        }

        return urlencode($sOUt);
    }

    static private function _getUserPassSalt($username, $password) {
        //TODO XXX是什么-zx
        return md5($username . $password . 'xxxx');
    }

    function getOnlineList() {
        
    }

    function getUserCount() {
        
    }

    function remove() {
        
    }

    //可逆的加解密函数
    static public function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
        $string = str_replace(' ', '+', $string);
        $ckey_length = 4;

        $key = md5($key ? $key : _UC_KEY);
        $keya = md5(substr($key, 0, 16));
        $keyb = md5(substr($key, 16, 16));
        $keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';

        $cryptkey = $keya . md5($keya . $keyc);
        $key_length = strlen($cryptkey);

        $string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
        $string_length = strlen($string);

        $result = '';
        $box = range(0, 255);

        $rndkey = array();
        for ($i = 0; $i <= 255; $i++) {
            $rndkey[$i] = ord($cryptkey[$i % $key_length]);
        }

        for ($j = $i = 0; $i < 256; $i++) {
            $j = ($j + $box[$i] + $rndkey[$i]) % 256;
            $tmp = $box[$i];
            $box[$i] = $box[$j];
            $box[$j] = $tmp;
        }

        for ($a = $j = $i = 0; $i < $string_length; $i++) {
            $a = ($a + 1) % 256;
            $j = ($j + $box[$a]) % 256;
            $tmp = $box[$a];
            $box[$a] = $box[$j];
            $box[$j] = $tmp;
            $result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
        }

        if ($operation == 'DECODE') {
            if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
                return substr($result, 26);
            } else {
                return '';
            }
        } else {
            return $keyc . str_replace('=', '', base64_encode($result));
        }
    }

    //初始化合作站点 的全域cookie 的sid设置地址
    static private function _createCoSitesInfo() {
        $_a = explode('.', $_SERVER['HTTP_HOST']);
        $_siteSurfix = $_a[count($_a) - 1];
        $site_all = array();
        //TODO  这里设置子系统设置cookeie的地址还有key
        $site_center = array(
            'url' => 'http://' . $_SERVER['HTTP_HOST'] . '/SSO/Api-Center.php',
            'key' => 'cnvpSSOcenter',
        );
        array_push($site_all, $site_center);
        $siteInDB = M('app')->select();
        foreach ($siteInDB as $k => $v) {
            $siteTmp = array(
                //TODO  这里设置子系统设置cookeie的地址还有key
                'url' => $v['url'] . '/SSO/Api.php',
                'key' => $v['token'],
            );
            array_push($site_all, $siteTmp);
        }
        self::$_coSitesInfo = $site_all;
    }

    //建立分站点信息和站点标识的映射关系表
    static private function _createSitesMap() {
        self::$_sitesMap = array(
            //子站1
            1 => array(
                'logoutUrl' => 'http://hostname1/user/api/logout_user.php',
            ),
            //子站2
            1 => array(
                'logoutUrl' => 'http://hostname2/user/api/logout_user.php',
            ),
            //子站3
            1 => array(
                'logoutUrl' => 'http://hostname3/user/api/logout_user.php',
            ),
        );
    }

    static private function userAuth($username, $pwd) {
        $M = M("Admin");
        $w['username'] = $username;
        if ($M->where($w)->count() >= 1) {
            $info = $M->where($w)->find();
            if ($info['status'] == 0) {
                return array('status' => 0, 'info' => "你的账号被禁用，有疑问联系管理员吧");
            }
            if ($info['pwd'] == encrypt($pwd)) {

                $loginMarked = C("TOKEN");
                $loginMarked = md5($loginMarked['admin_marked']);
                $shell = $info['aid'] . md5($info['pwd'] . C('AUTH_CODE'));
                $_SESSION[$loginMarked] = "$shell";
                $shell.= "_" . time();
                setcookie($loginMarked, "$shell", 0, "/");
                $_SESSION['my_info'] = $info;
                return array('status' => 1, 'info' => "登录成功", 'userinfo' => $info);
            } else {
                return array('status' => 0, 'info' => "账号或密码错误");
            }
        } else {
            return array('status' => 0, 'info' => "账号不存在：" . $datas["username"] . '的管理员账号！');
        }
    }

}

// <editor-fold defaultstate="collapsed" desc="无用类，仅作代码备份，日后可删除">
class CnvpSSOSever {

    static public function userLogin($username, $psw, $ip = '', $siteFlag = '', $remember = false) {
        $data['username'] = $username;
        $data['pwd'] = $psw;
        //验证登陆信息
        $returnLoginInfo = $this->userAuth($data);
        //保存SEESION或者COOKIE
        if ($returnLoginInfo['resultFlag'] == 1) {
            $map = array();
            // 支持使用绑定帐号登录
            $map['username'] = $_POST['username'];
            import('ORG.Util.RBAC');
            $authInfo = RBAC::authenticate($map);
            $_SESSION[C('USER_AUTH_KEY')] = $authInfo['id'];
            $_SESSION['username'] = $authInfo['username'];
            if ($authInfo['username'] == C('ADMIN_AUTH_KEY')) {
                $_SESSION[C('ADMIN_AUTH_KEY')] = true;
            }
            // 缓存访问权限
            RBAC::saveAccessList();
            session_start();
            $returnLoginInfo['sessID'] = session_id();
            //生成所有站点登录脚本
            $synScript = '<script type="text/javascript" src="http://' . $_SERVER['SERVER_NAME'] . ':' . $_SERVER['SERVER_PORT'] . $_SERVER['PHP_SELF'] . '"></script>';
            $returnLoginInfo['script'] = $synScript;
        }
        return xml_serialize($returnLoginInfo);
    }

    public function serverTimestamp() {
        return time();
    }

    private function userAuth($datas) {
        $M = M("Admin");
        $w['username'] = $username;
        if ($M->where($w)->count() >= 1) {
            $info = $M->where($w)->find();
            if ($info['status'] == 0) {
                return array('status' => 0, 'info' => "你的账号被禁用，有疑问联系管理员吧");
            }
            if ($info['pwd'] == encrypt($datas['pwd'])) {

                $loginMarked = C("TOKEN");
                $loginMarked = md5($loginMarked['admin_marked']);
                $shell = $info['aid'] . md5($info['pwd'] . C('AUTH_CODE'));
                $_SESSION[$loginMarked] = "$shell";
                $shell.= "_" . time();
                setcookie($loginMarked, "$shell", 0, "/");
                $_SESSION['my_info'] = $info;
                return array('resultFlag' => 1, 'info' => "登录成功", 'userinfo' => $info);
            } else {
                return array('resultFlag' => 0, 'info' => "账号或密码错误");
            }
        } else {
            return array('resultFlag' => 0, 'info' => "账号不存在：" . $datas["username"] . '的管理员账号！');
        }
    }

}